// Copyright 2018 Valerie Young. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-asyncgenerator-prototype-throw
description: throw rejects promise when `this` value not an object
info: |
  AsyncGenerator.prototype.throw ( exception )
  1. Let generator be the this value.
  2. Let completion be Completion{[[Type]]: throw, [[Value]]: exception,
     [[Target]]: empty}.
  3. Return ! AsyncGeneratorEnqueue(generator, completion).

  AsyncGeneratorEnqueue ( generator, completion )
  ...
  3. If Type(generator) is not Object, or if generator does not have an
     [[AsyncGeneratorState]] internal slot, then
    a. Let badGeneratorError be a newly created TypeError object.
    b. Perform ! Call(promiseCapability.[[Reject]], undefined, « badGeneratorError »).
    c. Return promiseCapability.[[Promise]].

flags: [async]
features: [async-iteration]
---*/

function Test() {
    async function* g() {}
    var AsyncGeneratorPrototype = Object.getPrototypeOf(g).prototype;

    var symbol = Symbol();

    var testPromises = [
      AsyncGeneratorPrototype.throw.call(undefined).then(
        function () {
          throw new Test262Error("AsyncGeneratorPrototype.throw should reject promise" +
                                 " when `this` value `undefined`");
        },
        function (e) {
          if (!(e instanceof TypeError)) {
           throw new Test262Error("(undefined) expected TypeError but got " + e);
          }
        }
      ),
      AsyncGeneratorPrototype.throw.call(1).then(
        function () {
          throw new Test262Error("AsyncGeneratorPrototype.throw should reject promise" +
                                 " when `this` value is a Number");
        },
        function (e) {
          if (!(e instanceof TypeError)) {
           throw new Test262Error("(Number) expected TypeError but got " + e);
          }
        }
      ),
      AsyncGeneratorPrototype.throw.call("string").then(
        function () {
          throw new Test262Error("AsyncGeneratorPrototype.throw should reject promise" +
                                 " when `this` value is a String");
        },
        function (e) {
          if (!(e instanceof TypeError)) {
           throw new Test262Error("(String) expected TypeError but got " + e);
          }
        }
      ),
      AsyncGeneratorPrototype.throw.call(null).then(
        function () {
          throw new Test262Error("AsyncGeneratorPrototype.throw should reject promise" +
                                 " when `this` value `null`");
        },
        function (e) {
          if (!(e instanceof TypeError)) {
           throw new Test262Error("(null) expected TypeError but got " + e);
          }
        }
      ),
      AsyncGeneratorPrototype.throw.call(true).then(
        function () {
          throw new Test262Error("AsyncGeneratorPrototype.throw should reject promise" +
                                 " when `this` value is a Boolean");
        },
        function (e) {
          if (!(e instanceof TypeError)) {
           throw new Test262Error("(Boolean) expected TypeError but got " + e);
          }
        }
      ),
      AsyncGeneratorPrototype.throw.call(symbol).then(
        function () {
          throw new Test262Error("AsyncGeneratorPrototype.throw should reject promise" +
                                 " when `this` value is a Symbol");
        },
        function (e) {
          if (!(e instanceof TypeError)) {
           throw new Test262Error("(Symbol) expected TypeError but got " + e);
          }
        }
      )
    ]

    Promise.all(testPromises).then(() => {}).then($DONE, $DONE)
}

// preheat
const NUMBER_OF_PREHEAT = 1;
for (let i = 0; i < NUMBER_OF_PREHEAT; i++) {
    Test();
}

ArkTools.jitCompileAsync(Test);
assert.sameValue(ArkTools.waitJitCompileFinish(Test), true, '[JIT] JIT disabled.');

// test
const NUMBER_OF_TEST = 1; // or 2
for (let i = 0; i < NUMBER_OF_TEST; i++) {
    Test();
}
